/***** Example of Isometric Projection
 *
 * This example shows how to project a large amount of 3D points to the screen
 * without any perpoint trig functions.  Once you have these points in screen-
 * space you can blit sprites, draw polygons, or whatever you like.
 */

/* I prefer floats to Allegro's fixed point numbers so we need math.h for it's
 * sin() and cos() functions.
 */
#include <math.h>
#include <allegro.h>

int main(void)
{
  float pi = 3.14;
  float offset = pi * -0.5;
  float rotation = pi*0.25;
  float elevation = 1.1;
  float zoom = 20.0;
  float x, y, z, screen_x, screen_y;
  float right_x, right_y, front_x, front_y, up_x, up_y; 

  /* initialize Allegro and setup a double buffer */   
  BITMAP *buffer;

  if (allegro_init() != 0)
    return 1;
  install_timer();
  install_keyboard();

  if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0) != 0) 
  {
   if (set_gfx_mode(GFX_SAFE, 320, 200, 0, 0) != 0)
    {
   set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
   allegro_message("Unable to set any graphic mode\n%s\n", allegro_error);
   return 1;
    }
  }
  buffer = create_bitmap(SCREEN_W, SCREEN_H);

  /* main loop */    
  while (!key[KEY_ESC])
  {
    clear_bitmap(buffer);

    /* user input to control the various rotations */
    if (key[KEY_4_PAD]) rotation += 0.01;
    if (key[KEY_6_PAD]) rotation -= 0.01;    
    if (key[KEY_8_PAD]) elevation += 0.01;
    if (key[KEY_2_PAD]) elevation -= 0.01;    
    if (key[KEY_9_PAD]) zoom *= 1.01;    
    if (key[KEY_3_PAD]) zoom *= 0.99;

    /* precalculated vectors */
    right_x = cos(rotation);
    right_y = sin(rotation) * cos(elevation);
    front_x = -sin(rotation);
    front_y = cos(rotation) * cos(elevation);
    up_x = 0.0;
    up_y = sin(elevation);

    for (x=-5.0; x<=5.0; x+=0.1)
    {
      for (y=-5.0; y<=5.0; y+=0.1)
      {
        z = sin(x) + cos(y);
        
        screen_x = x * right_x + y * front_x + z * up_x;
        screen_y = x * right_y + y * front_y + z * up_y; 

        screen_x *= zoom;
        screen_y *= zoom;

        putpixel(buffer, 
                (int)floor(screen_x + SCREEN_W * 0.5), 
                (int)floor(screen_y + SCREEN_H * 0.5),
                makecol(255, 255, 255));
      }
    }

    textprintf_ex(buffer, font, 10, 10, makecol(255, 255, 255), -1, 
                  "rotation.: % 06.2f", rotation);
    textprintf_ex(buffer, font, 10, 20, makecol(255, 255, 255), -1, 
                  "elevation: % 06.2f", elevation);

    blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
    yield_timeslice();
  }

  destroy_bitmap(buffer);
  return 0;
}

END_OF_MAIN();

